package com.app.myApp.control;

import com.app.myApp.dao.ChatHistoryDAO;
import com.app.myApp.dao.KnowledgeFilesDAO;
import com.app.myApp.dao.RobotAndKnowledgeBasesDAO;
import com.app.myApp.dao.SystemKnowledgeFilesDAO;
import com.app.myApp.dataobject.ChatHistoryDO;
import com.app.myApp.dataobject.KnowledgeFilesDO;
import com.app.myApp.dataobject.RobotAndKnowledgeBasesDO;
import com.app.myApp.dataobject.SystemKnowledgeFilesDO;
import com.app.myApp.model.Response;
import com.app.myApp.model.Robot;
import com.app.myApp.utils.FileTextExtractor;
import com.huaban.analysis.jieba.JiebaSegmenter;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.model.COSObject;
import com.qcloud.cos.model.GetObjectRequest;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.codec.ServerSentEvent;
import org.springframework.web.bind.annotation.*;
import org.springframework.ai.ollama.OllamaChatModel;
import reactor.core.publisher.Flux;

import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

@RestController
public class ChatHistoryController {
    @Autowired
    private ChatHistoryDAO chatHistoryDAO;

    @Autowired
    private OllamaChatModel ollamaChatModel;

    // RAG相关依赖注入
    @Autowired
    private RobotAndKnowledgeBasesDAO robotAndKnowledgeBasesDAO;

    @Autowired
    private KnowledgeFilesDAO knowledgeFilesDAO;

    @Autowired
    private SystemKnowledgeFilesDAO systemKnowledgeFilesDAO;

    @Autowired
    private COSClient cosClient;

    @Autowired
    private FileTextExtractor fileTextExtractor;

    @Value("${tencent.cos.bucket-name}")
    private String bucketName;

    @Value("${tencent.cos.base-url}")
    private String cosBaseUrl;

    @PostMapping("/chat/selectChatContent")
    public ResponseEntity<Response> updateAssistant(@RequestBody Robot robot) {
        List<ChatHistoryDO> chatHistoryDOS = chatHistoryDAO.selectByRobotId(robot.getRobotId());
        return chatHistoryDOS.isEmpty()
                ? new ResponseEntity<>(Response.error("查询聊天记录失败"), HttpStatus.OK)
                : new ResponseEntity<>(Response.success(chatHistoryDOS), HttpStatus.OK);
    }

    @PostMapping("/chat/deleteChatContent")
    public ResponseEntity<Response> deleteChatContent(@RequestBody Robot robot) {
        int rows = chatHistoryDAO.deleteById(robot.getRobotId());
        return rows > 0
                ? new ResponseEntity<>(Response.success("删除聊天记录成功"), HttpStatus.OK)
                : new ResponseEntity<>(Response.error("删除聊天记录失败"), HttpStatus.OK);
    }

    @GetMapping("/chatStream")
    public Flux<ServerSentEvent<String>> chat(
            @RequestParam("promptContent") String promptContent,
            @RequestParam("robotId") int robotId) {

        System.out.println("正在回答...");
        // 保存用户消息到数据库
        ChatHistoryDO userChatHistoryDO = new ChatHistoryDO();
        userChatHistoryDO.setContent(promptContent);
        userChatHistoryDO.setFrom("User");
        userChatHistoryDO.setRobotId(robotId);
        userChatHistoryDO.setCreated_at(LocalDateTime.now());
        chatHistoryDAO.insert(userChatHistoryDO);

        // 构建上下文：知识库文本（RAG） + 历史聊天记录
        StringBuilder fullPrompt = new StringBuilder();

        // 获取知识库文本，传入promptContent作为参数
        String knowledgeText = getKnowledgeTextByRobotId(robotId, promptContent);
        System.out.println("这里");
        System.out.println(knowledgeText);
        System.out.println("还有这里");
        if (!knowledgeText.isEmpty()) {
            fullPrompt.append("【知识库参考内容】：\n")
                    .append(knowledgeText)
                    .append("\n\n【注意】：优先基于上述知识库内容回答，若知识库无相关信息再自主回答。\n\n");
        }

        // 添加历史聊天记录上下文
        List<ChatHistoryDO> historyList = chatHistoryDAO.selectByRobotId(robotId);
        String historyText = historyList.stream()
                .map(history -> history.getFrom() + ": " + history.getContent())
                .collect(Collectors.joining("\n"));
        if (!historyText.isEmpty()) {
            fullPrompt.append("【历史聊天记录】：\n")
                    .append(historyText)
                    .append("\n\n");
        }

        // 添加当前用户输入
        fullPrompt.append("User: ").append(promptContent).append("\nAI: ");

        // 调用大模型生成流式响应
        StringBuilder aiResponseSum = new StringBuilder();
        return ollamaChatModel.stream(fullPrompt.toString()).map(token -> {
            aiResponseSum.append(token);
            return ServerSentEvent.builder(token).event("message").build();
        }).doOnComplete(() -> {
            // 保存AI回复到数据库
            ChatHistoryDO aiChatHistory = new ChatHistoryDO();
            aiChatHistory.setContent(aiResponseSum.toString());
            aiChatHistory.setFrom("AI");
            aiChatHistory.setRobotId(robotId);
            aiChatHistory.setCreated_at(LocalDateTime.now());
            chatHistoryDAO.insert(aiChatHistory);
        });
    }

    private String getKnowledgeTextByRobotId(int robotId, String promptContent) {
        try {
            // 查询机器人绑定的知识库
            RobotAndKnowledgeBasesDO binding = robotAndKnowledgeBasesDAO.selectByRobotId((long) robotId);
            if (binding == null || binding.getKnowledge_base_id() == null) {
                System.out.println("未绑定知识库");
                return ""; // 未绑定知识库
            }
            System.out.println("绑定知识库了");
            String kbId = binding.getKnowledge_base_id();
            String kbType = binding.getFrom(); // "system" 或 "personal"
            StringBuilder knowledgeText = new StringBuilder();

            // 根据知识库类型查询文件列表
            List<? extends Object> fileList;
            if ("system".equals(kbType)) {
                fileList = systemKnowledgeFilesDAO.selectBySystemKbId(kbId);
            } else {
                fileList = knowledgeFilesDAO.selectByKnowledgeId(kbId);
            }

            // 遍历文件，从COS下载并提取文本
            for (Object fileObj : fileList) {
                String cosFilePath = "";
                String mimeType = "";
                String fileName = "";

                if (fileObj instanceof SystemKnowledgeFilesDO) {
                    SystemKnowledgeFilesDO sysFile = (SystemKnowledgeFilesDO) fileObj;
                    cosFilePath = sysFile.getPath();
                    mimeType = sysFile.getType();
                    fileName = sysFile.getName();
                } else if (fileObj instanceof KnowledgeFilesDO) {
                    KnowledgeFilesDO userFile = (KnowledgeFilesDO) fileObj;
                    cosFilePath = userFile.getPath();
                    mimeType = userFile.getType();
                    fileName = userFile.getName();
                }

                if (cosFilePath.isEmpty()) {
                    continue;
                }

                // 从COS下载文件字节数组
                byte[] fileBytes = downloadFileFromCOS(cosFilePath);
                if (fileBytes == null) {
                    continue;
                }


                // 提取文件文本
                String fileText = fileTextExtractor.extractText(fileBytes, mimeType);
                if (fileText.isEmpty()) {
                    continue;
                }


                if (isTextRelevant(fileText, promptContent)) {
                    knowledgeText.append("文件名：").append(fileName).append("\n")
                            .append("内容：").append(fileText).append("\n\n");
                }
            }

            return knowledgeText.toString().trim();//这里是空的
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    private byte[] downloadFileFromCOS(String cosFilePath) {
        try {
            GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, cosFilePath);
            try (COSObject cosObject = cosClient.getObject(getObjectRequest);
                 InputStream inputStream = cosObject.getObjectContent()) {
                return IOUtils.toByteArray(inputStream);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    private boolean isTextRelevant(String fileText, String prompt) {
        JiebaSegmenter segmenter = new JiebaSegmenter();
        List<String> promptWords = segmenter.sentenceProcess(prompt.toLowerCase());
        String lowerFile = fileText.toLowerCase();

        for (String word : promptWords) {
            if (word.length() > 1 && lowerFile.contains(word)) {
                return true;
            }
        }
        return false;
    }
}
